package gameservice

import (
	"admin100/app/dao/gamedao"
	"admin100/app/model/commonmodel"
	"admin100/app/model/gamemodel"
	"admin100/app/service/centerservice"
	"admin100/app/service/commonservice"
	"admin100/library/define"
	"admin100/library/define/defErr"
	"admin100/library/utils"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/gogf/gf/frame/g"
)

var Log = &logService{}

type logService struct{}

func (s *logService) List(req *gamemodel.PlayerLoginLogListReq) ([]*gamemodel.PlayerLoginLog, int) {
	if req.PlayerName != "" {
		serverId, _ := commonservice.GamePlayer.SplitPlayerName(req.PlayerName)
		sNode := centerservice.CGameServer.FetchNodeStrByPtIdAndSid(req.PlatformId, serverId)
		player := commonservice.GamePlayer.GetPlayerByPlatformIdAndNickname(sNode, req.PlayerName)
		req.PlayerId = int(player.Id)
	}

	var (
		node   = centerservice.CGameServer.FetchNodeStrByPtIdAndSid(req.PlatformId, req.ServerId)
		gameDb = gamedao.NewPlayerLoginLogDao(node)
		column = gameDb.Columns
	)

	m := gameDb.WhereValNotEmpty(g.Map{
		column.Ip: req.Ip,
	})
	if req.PlayerId > 0 {
		m.Where(column.PlayerId, req.PlayerId)
	}
	if req.StartTime > 0 {
		m = m.Where(column.Timestamp+" between ? and ?", req.StartTime, req.EndTime)
	}
	m1 := m.Clone()
	data, err := m.Page(req.Cur, req.PNum).Order(column.Id + " asc").FindAll()
	defErr.SelectRetPanic(err, data, define.DataOptFail)
	total, err := m1.Count()
	if err != nil {
		defErr.Panic(define.DataOptFail, err.Error())
	}

	var pids []int
	for _, v := range data {
		pids = append(pids, int(v.PlayerId))
	}
	pids = utils.RemoveReIntData(pids)
	playerGameDao := gamedao.NewPlayerDao(node)
	playerNames := playerGameDao.GetPlayerNames(pids)
	for _, v := range data {
		if name, ok := playerNames[int(v.PlayerId)]; ok {
			v.PlayerName = name
		}
	}

	return data, total
}

func (s *logService) OnlineList(req *gamemodel.PlayerOnlineLogListReq) ([]*gamemodel.PlayerOnlineLog, int) {
	if req.PlayerName != "" {
		serverId, _ := commonservice.GamePlayer.SplitPlayerName(req.PlayerName)
		sNode := centerservice.CGameServer.FetchNodeStrByPtIdAndSid(req.PlatformId, serverId)
		player := commonservice.GamePlayer.GetPlayerByPlatformIdAndNickname(sNode, req.PlayerName)
		req.PlayerId = int(player.Id)
	}
	var (
		node   = centerservice.CGameServer.FetchNodeStrByPtIdAndSid(req.PlatformId, req.ServerId)
		gameDb = gamedao.NewPlayerOnlineLogDao(node)
		column = gameDb.Columns
	)

	m := gameDb.Fields("*")
	if req.PlayerId > 0 {
		m = m.Where(column.PlayerId, req.PlayerId)
	}
	if req.StartTime > 0 {
		m = m.Where(column.OfflineTime+" between ? and ?", req.StartTime, req.EndTime)
	}
	m1 := m.Clone()
	data, err := m.Page(req.Cur, req.PNum).Order(column.Id + " desc").FindAll()
	defErr.SelectRetPanic(err, data, define.DataOptFail)
	total, err := m1.Count()
	if err != nil {
		defErr.Panic(define.DataOptFail, err.Error())
	}

	var pids []int
	for _, v := range data {
		pids = append(pids, int(v.PlayerId))
	}
	playerGameDao := gamedao.NewPlayerDao(node)
	playerNames := playerGameDao.GetPlayerNames(pids)
	for _, v := range data {
		if name, ok := playerNames[int(v.PlayerId)]; ok {
			v.PlayerName = name
		}
	}

	return data, total

}

type PropLogReq struct {
	*commonmodel.PageInfo
	PlatformId string `v:"required#平台ID不能为空" json:"platformId"`
	ServerId   string `v:"required#serverId不能为空" json:"serverId"`
	Ip         string
	PlayerId   int
	PlayerName string `v:"required#用户名不有为空"`
	Datetime   int    `json:"datetime"`
	StartTime  int
	EndTime    int
	PropType   int
	PropId     int
	OpType     int
	Type       int //1：获得 2：消耗
}

type PlayerPropLog struct {
	Id          int    `json:"id"`
	PlayerId    int    `json:"playerId"`
	PlayerName  string `json:"playerName" gorm:"-"`
	PropType    int    `json:"propType"`
	PropId      int    `json:"propId"`
	OpType      int    `json:"opType"`
	OpTime      int    `json:"opTime"`
	ChangeValue int    `json:"changeValue"`
	NewValue    int    `json:"newValue"`
}

func (s *logService) GetPlayerPropLogList(sNode string, req *PropLogReq) ([]*PlayerPropLog, int) {
	t := time.Unix(int64(req.Datetime), 0)
	logDir := fmt.Sprintf("%d_%d_%d", t.Year(), t.Month(), t.Day())

	grepParam := ""
	logFile := "player_prop_log.log"
	grepParam += fmt.Sprintf(" | /usr/bin/grep \\{p,%d\\} ", req.PlayerId)
	if req.PropType > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{pT,%d\\} ", req.PropType)
		if req.PropType == 7 {
			logFile = "player_special_prop_log.log"
		}
	}
	if req.PropId > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{pI,%d\\} ", req.PropId)
	}
	if req.OpType > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{l,%d\\} ", req.OpType)
	}
	sshKey := g.Cfg().GetString("game.ssh_key")
	sshPort := g.Cfg().GetString("game.ssh_port")
	nodeName := strings.Split(sNode, "@")[0]
	nodeIp := strings.Split(sNode, "@")[1]

	nodeIp = "root@192.168.31.100"

	cmd := fmt.Sprintf("ssh -i %s -p%s %s ' /usr/bin/cat /data/log/game/%s/%s/%s %s'", sshKey, sshPort, nodeIp, nodeName, logDir, logFile, grepParam)
	cmd = "/usr/bin/cat ~/tmp/player_prop_log.log  | /usr/bin/grep \\{p,12711\\}"
	out := utils.ExecShell(cmd)
	if out == "" {
		return nil, 0
	}

	reg := regexp.MustCompile(`(\d+):(\d+):(\d+)\s+\[{p,(\d+)},{pT,(\d+)},{pI,(\d+)},{l,(\d+)},{c,([-\d]+)},{n,(\d+)}\]`)
	matchArray := reg.FindAllStringSubmatch(out, -1)
	//g.Log().Debug("%+v", matchArray)
	data := make([]*PlayerPropLog, 0)
	for _, e := range matchArray {
		//g.Log().Debug("%+v", e)
		h, err := strconv.Atoi(e[1])
		defErr.IfPanic(err, define.Fail)
		m, err := strconv.Atoi(e[2])
		defErr.IfPanic(err, define.Fail)
		s, err := strconv.Atoi(e[3])
		defErr.IfPanic(err, define.Fail)

		time := h*60*60 + m*60 + s
		if req.StartTime > 0 && req.EndTime > 0 {
			if time < req.StartTime || time > req.EndTime {
				continue
			}
		}
		t := req.Datetime + time
		playerId, err := strconv.Atoi(e[4])
		defErr.IfPanic(err, define.Fail)
		propType, err := strconv.Atoi(e[5])
		defErr.IfPanic(err, define.Fail)
		propId, err := strconv.Atoi(e[6])
		defErr.IfPanic(err, define.Fail)
		logType, err := strconv.Atoi(e[7])
		defErr.IfPanic(err, define.Fail)
		change, err := strconv.Atoi(e[8])
		defErr.IfPanic(err, define.Fail)
		new, err := strconv.Atoi(e[9])
		defErr.IfPanic(err, define.Fail)
		data = append(data, &PlayerPropLog{
			PlayerId:    playerId,
			PropType:    propType,
			PropId:      propId,
			OpType:      logType,
			ChangeValue: change,
			NewValue:    new,
			OpTime:      t,
		})
	}
	len := len(data)
	limit := req.PNum
	start := req.Cur
	if start >= len {
		return nil, len
	}
	if start+limit > len {
		limit = len - start
	}
	g.Log().Debug(len, start, limit)
	return data[start : start+limit], len
}

type PlayerAttrLogReq struct {
	*commonmodel.PageInfo
	PlatformId string
	ServerId   string `json:"serverId"`
	Ip         string
	PlayerId   int
	PlayerName string
	Datetime   int `json:"datetime"`
	StartTime  int
	EndTime    int
	FunctionId int `json:"functionId"`
	Type       int // 1：减少 `json:"type"`
}

type PlayerAttrLog struct {
	Id         int    `json:"id"`
	PlayerId   int    `json:"playerId"`
	PlayerName string `json:"playerName"`
	FunctionId int    `json:"functionId"`
	Power      int    `json:"power"`
	ChangeTime int    `json:"changeTime"`
	AddPower   int    `json:"addPower"`
}

func (s *logService) GetPlayerAttrLogList(sNode string, req *PlayerAttrLogReq) ([]*PlayerAttrLog, int) {
	t := time.Unix(int64(req.Datetime), 0)
	logDir := fmt.Sprintf("%d_%d_%d", t.Year(), t.Month(), t.Day())

	grepParam := ""
	grepParam += fmt.Sprintf(" | /usr/bin/grep \\{pid,%d\\} ", req.PlayerId)
	if req.FunctionId > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{fid,%d\\} ", req.FunctionId)
	}
	if req.Type > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{add,- ")
	}
	sshKey := g.Cfg().GetString("game.ssh_key")
	sshPort := g.Cfg().GetString("game.ssh_port")
	nodeName := strings.Split(sNode, "@")[0]
	nodeIp := strings.Split(sNode, "@")[1]
	cmd := fmt.Sprintf("ssh -i %s -p%s %s ' /usr/bin/cat /data/log/game/%s/%s/player_attr_log.log %s'", sshKey, sshPort, nodeIp, nodeName, logDir, grepParam)
	cmd = "/usr/bin/cat ~/tmp/player_attr_log.log  | /usr/bin/grep pid,12711\\}"
	out := utils.ExecShell(cmd)
	if out == "" {
		return nil, 0
	}

	reg := regexp.MustCompile(`(\d+):(\d+):(\d+)\s+\[{pid,(\d+)},{fid,(\d+)},{p,(\d+)},{add,([-\d]+)},{at,(\d+)},{de,(\d+)}\]`)
	matchArray := reg.FindAllStringSubmatch(out, -1)
	//g.Log().Debug("matchArray:%+v", matchArray)
	data := make([]*PlayerAttrLog, 0)
	for _, e := range matchArray {
		h, err := strconv.Atoi(e[1])
		defErr.IfPanic(err, define.Fail)
		m, err := strconv.Atoi(e[2])
		defErr.IfPanic(err, define.Fail)
		s, err := strconv.Atoi(e[3])
		defErr.IfPanic(err, define.Fail)

		time := h*60*60 + m*60 + s
		if req.StartTime > 0 && req.EndTime > 0 {
			if time < req.StartTime || time > req.EndTime {
				continue
			}
		}
		t := req.Datetime + time
		playerId, err := strconv.Atoi(e[4])
		defErr.IfPanic(err, define.Fail)
		fId, err := strconv.Atoi(e[5])
		defErr.IfPanic(err, define.Fail)
		power, err := strconv.Atoi(e[6])
		defErr.IfPanic(err, define.Fail)
		addPower, err := strconv.Atoi(e[7])
		defErr.IfPanic(err, define.Fail)
		data = append(data, &PlayerAttrLog{
			PlayerId:   playerId,
			FunctionId: fId,
			Power:      power,
			AddPower:   addPower,
			ChangeTime: t,
		})
	}
	len := len(data)
	limit := req.PNum
	start := req.Cur
	if start >= len {
		return nil, len
	}
	if start+limit > len {
		limit = len - start
	}
	g.Log().Debug(len, start, limit)
	return data[start : start+limit], len

}

type PlayerMailLogReq struct {
	*commonmodel.PageInfo
	PlatformId string
	ServerId   string `json:"serverId"`
	Ip         string
	PlayerId   int
	PlayerName string
	Datetime   int `json:"datetime"`
	StartTime  int
	EndTime    int
	LogType    int `json:"logType"`
	Type       int //1：增加 2：删除 3：提取附件 `json:"type"`
}

type Prop struct {
	PropType int `json:"propType,omitempty"`
	PropId   int `json:"propId,omitempty"`
	PropNum  int ` json:"propNum,omitempty"`
}

type PlayerMailLog struct {
	Id         int    `json:"id"`
	PlayerId   int    `json:"playerId"`
	PlayerName string `json:"playerName"`
	ChangeType string `json:"changeType"`
	LogT       int    `json:"logT"`
	MailIdList string `json:"mailIdList"`
	ItemList   []Prop `json:"itemList"`
	//ItemList 	string  `json:"itemList"`
	ChangeTime int `json:"changeTime"`
}

func (s *logService) GetPlayerMailLogList(sNode string, req *PlayerMailLogReq) ([]*PlayerMailLog, int) {
	t := time.Unix(int64(req.Datetime), 0)
	logDir := fmt.Sprintf("%d_%d_%d", t.Year(), t.Month(), t.Day())

	grepParam := ""
	grepParam += fmt.Sprintf(" | /usr/bin/grep \\{pid,%d\\} ", req.PlayerId)
	if req.Type > 0 {
		var changeTypeStr = "addMail"
		if req.Type == 3 {
			changeTypeStr = "item_mail"
		}
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{cT,%s\\} ", changeTypeStr)
	}
	if req.LogType > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{log,%d\\} ", req.LogType)
	}
	sshKey := g.Cfg().GetString("game.ssh_key")
	sshPort := g.Cfg().GetString("game.ssh_port")
	nodeName := strings.Split(sNode, "@")[0]
	nodeIp := strings.Split(sNode, "@")[1]
	cmd := fmt.Sprintf("ssh -i %s -p%s %s ' /usr/bin/cat /data/log/game/%s/%s/player_mail_log.log %s'", sshKey, sshPort, nodeIp, nodeName, logDir, grepParam)
	//cmd := fmt.Sprintf("ssh -i /root/.ssh/thyz_87 -p22 %s ' /usr/bin/cat /data/log/game/%s/%s/player_mail_log.log %s'", nodeIp, nodeName, logDir, grepParam)
	//g.Log().Debug("-----cmd: %+v", cmd)
	cmd = "/usr/bin/cat ~/tmp/player_mail_log.log  | /usr/bin/grep pid,12711\\}"
	out := utils.ExecShell(cmd)
	if out == "" {
		return nil, 0
	}

	reg := regexp.MustCompile(`(\d+):(\d+):(\d+)\s+\[{pid,(\d+)},{cT,(\w+)},{log,(\d+)},{mailL,(.*)},{itemL,(.*)}\]`)
	matchArray := reg.FindAllStringSubmatch(out, -1)
	data := make([]*PlayerMailLog, 0)
	for _, e := range matchArray {
		h, err := strconv.Atoi(e[1])
		defErr.IfPanic(err, define.Fail)
		m, err := strconv.Atoi(e[2])
		defErr.IfPanic(err, define.Fail)
		s, err := strconv.Atoi(e[3])
		defErr.IfPanic(err, define.Fail)

		time := h*60*60 + m*60 + s
		if req.StartTime > 0 && req.EndTime > 0 {
			if time < req.StartTime || time > req.EndTime {
				continue
			}
		}
		t := req.Datetime + time
		playerId, err := strconv.Atoi(e[4])
		defErr.IfPanic(err, define.Fail)
		changType := e[5]
		logType, err := strconv.Atoi(e[6])
		defErr.IfPanic(err, define.Fail)
		mailIdList := e[7]
		itemListStr := strings.Replace(e[8], "\"", "", -1)
		var itemList []Prop
		if itemListStr != "[]" {
			itemListStr1 := strings.Replace(strings.Replace(itemListStr, "[{", "", -1), "}]", "", -1)
			line := strings.Split(itemListStr1, "},{")
			for _, PropStr := range line {
				PropList := strings.Split(PropStr, ",")
				PropType, err := strconv.Atoi(PropList[0])
				defErr.IfPanic(err, define.Fail)
				PropId, err := strconv.Atoi(PropList[1])
				defErr.IfPanic(err, define.Fail)
				PropNum, err := strconv.Atoi(PropList[2])
				defErr.IfPanic(err, define.Fail)
				itemList = append(itemList, Prop{
					PropType: PropType,
					PropId:   PropId,
					PropNum:  PropNum,
				})
			}
		}
		defErr.IfPanic(err, define.Fail)
		data = append(data, &PlayerMailLog{
			PlayerId:   playerId,
			ChangeType: changType,
			MailIdList: mailIdList,
			ItemList:   itemList,
			LogT:       logType,
			ChangeTime: t,
		})
	}
	len := len(data)
	limit := req.PNum
	start := req.Cur
	if start >= len {
		return nil, len
	}
	if start+limit > len {
		limit = len - start
	}
	g.Log().Debug(len, start, limit)
	return data[start : start+limit], len

}

type PlayerActivityAwardLog struct {
	ActivityId int    `json:"activityId"`
	Rank       int    `json:"rank"`
	PlayerId   int    `json:"playerId"`
	PlayerName string `json:"playerName" gorm:"-"`
	Value      int    `json:"value"`
	ChangeTime int    `json:"changeTime"`
	AwardId    int    `json:"awardId"`
}

type ActivityAwardLogReq struct {
	*commonmodel.PageInfo
	PlatformId string
	ServerId   string `json:"serverId"`
	ServerType int
	PlayerId   int    `json:"playerId"`
	PlayerName string `json:"playerName" gorm:"-"`
	Datetime   int    `json:"datetime"`
	ActivityId int    `json:"activityId"`
}

func (s *logService) GetActivityAwardLogList(req *ActivityAwardLogReq) ([]*PlayerActivityAwardLog, int) {
	var node string
	var dirType string
	if req.ServerType == 7 {
		WarNodeList := centerservice.CGameNode.FetchNodeStrByPtAndType(req.PlatformId, req.ServerType)
		if len(WarNodeList) != 1 {
			return nil, 0
		}
		ServerNode := WarNodeList[0]
		node = ServerNode.Node
		dirType = "zone"
	} else {
		node = centerservice.CGameServer.FetchNodeStrByPtIdAndSid(req.PlatformId, req.ServerId)
		dirType = "game"
	}

	serverNode := centerservice.CGameServer.GetServerNode(node)
	if serverNode == nil {
		return nil, 0
	}

	sNode := serverNode.Node

	t := time.Unix(int64(req.Datetime), 0)
	logDir := fmt.Sprintf("%d_%d_%d", t.Year(), t.Month(), t.Day())
	g.Log().Debug("logDir:%s", logDir)

	grepParam := ""
	if req.ActivityId > 0 {
		grepParam += fmt.Sprintf(" | /usr/bin/grep \\{aId,%d\\} ", req.ActivityId)
	}
	sshKey := g.Cfg().GetString("game.ssh_key")
	sshPort := g.Cfg().GetString("game.ssh_port")
	nodeName := strings.Split(sNode, "@")[0]
	nodeIp := strings.Split(sNode, "@")[1]
	cmd := fmt.Sprintf("ssh -i %s -p%s %s ' /usr/bin/cat /data/log/%s/%s/%s/activity_award_log.log %s'", sshKey, sshPort, nodeIp, dirType, nodeName, logDir, grepParam)
	out := utils.ExecShell(cmd)

	reg := regexp.MustCompile(`(\d+):(\d+):(\d+)\s+\[{aId,(\d+)},{logT,(\d+)},{data,(.*)}\]`)
	matchArray := reg.FindAllStringSubmatch(out, -1)
	//g.Log().Debug("matchArray:%+v", matchArray)
	data := make([]*PlayerActivityAwardLog, 0)
	for _, e := range matchArray {
		playerStr := strings.Replace(e[6], "\"", "", -1)
		if playerStr == "[]" {
			continue
		}
		h, err := strconv.Atoi(e[1])
		defErr.IfPanic(err, define.Fail)
		m, err := strconv.Atoi(e[2])
		defErr.IfPanic(err, define.Fail)
		s, err := strconv.Atoi(e[3])
		defErr.IfPanic(err, define.Fail)
		time := h*60*60 + m*60 + s
		t := req.Datetime + time
		activityId, err := strconv.Atoi(e[4])
		defErr.IfPanic(err, define.Fail)
		//logType, err := strconv.Atoi(e[5])
		//utils.CheckError(err)
		//playerStr := e[6]
		playerStr1 := strings.Replace(strings.Replace(playerStr, "[{", "", -1), "}]", "", -1)
		line := strings.Split(playerStr1, "},{")
		for _, PlayerAwardStr := range line {
			AwardInfo := strings.Split(PlayerAwardStr, ",")
			PlayerId, err := strconv.Atoi(AwardInfo[0])
			defErr.IfPanic(err, define.Fail)
			if req.PlayerId > 0 {
				if req.PlayerId != PlayerId {
					continue
				}
			}
			Rank, err := strconv.Atoi(AwardInfo[1])
			defErr.IfPanic(err, define.Fail)
			Value, err := strconv.Atoi(AwardInfo[2])
			defErr.IfPanic(err, define.Fail)
			AwardId, err := strconv.Atoi(AwardInfo[3])
			defErr.IfPanic(err, define.Fail)
			data = append(data, &PlayerActivityAwardLog{
				PlayerId:   PlayerId,
				ActivityId: activityId,
				Rank:       Rank,
				Value:      Value,
				AwardId:    AwardId,
				ChangeTime: t,
			})
		}
	}
	len := len(data)
	if req.Order == "ascending" {
		for i, j := 0, len-1; i < j; i, j = i+1, j-1 {
			data[i], data[j] = data[j], data[i]
		}
	}
	limit := req.PNum
	start := req.Cur
	if start >= len {
		return nil, len
	}
	if start+limit > len {
		limit = len - start
	}
	g.Log().Debug(len, start, limit)
	return data[start : start+limit], len
}
